package ar.edu.itba.jMEBowling.scenario;

import java.util.ArrayList;

import ar.edu.itba.jMEBowling.Runner;
import ar.edu.itba.jMEBowling.utils.Helpers;

import com.jme.image.Texture;
import com.jme.math.Quaternion;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.Node;
import com.jme.scene.state.MaterialState;
import com.jme.scene.state.TextureState;
import com.jme.system.DisplaySystem;
import com.jme.util.TextureManager;
import com.jmex.physics.DynamicPhysicsNode;
import com.jmex.physics.PhysicsSpace;
import com.jmex.physics.material.Material;

public class TenPin {

	private static final float DELTAFALLEN = 0.2f;
	private ArrayList<Pin> pins;
	private ArrayList<DynamicPhysicsNode> dynamicPins;
	private ArrayList<Vector3f> locations;
	private Material pinMaterial;
	private ArrayList<Vector3f> locationBackup;

	public TenPin(String modelFileName, String textureFile,
			DisplaySystem displaySystem, PhysicsSpace physicsSpace,
			Node rootNode, Vector3f courtCenter, int xSeparation,
			int ySeparation) {

		generateLocations(courtCenter, xSeparation, ySeparation);
		pins = new ArrayList<Pin>();
		dynamicPins = new ArrayList<DynamicPhysicsNode>();
		locationBackup = new ArrayList<Vector3f>();

		int i = 0;

		// Material pinMaterial = Helpers.createMaterial("pinMaterial", 0.3f,
		// 0.2f, 0.6f);
		while (i < 10) {
			Pin pin = new Pin(modelFileName, "pin" + i);

			pins.add(pin);
			DynamicPhysicsNode node = physicsSpace.createDynamicNode();
			rootNode.attachChild(node);

			node.attachChild(pin.getMesh());

			node.setLocalTranslation(locations.get(i));
			pinMaterial = Helpers.getMaterial("pinMaterial", Material.WOOD
					.getDensity());

			node.setMaterial(pinMaterial);

			MaterialState ms = displaySystem.getRenderer()
					.createMaterialState();
			ms.setEmissive(ColorRGBA.white);
			node.setRenderState(ms);

			node.setCenterOfMass(pin.getMesh().getWorldBound().getCenter()
					.subtract(0, 0.1f, 0));
			node.setMass(1.5f);

			Texture t1 = TextureManager.loadTexture(Runner.class
					.getClassLoader().getResource(textureFile),
					Texture.MinificationFilter.Trilinear,
					Texture.MagnificationFilter.Bilinear);

			TextureState ts1 = displaySystem.getRenderer().createTextureState();
			ts1.setTexture(t1);
			node.setRenderState(ts1);
			node.generatePhysicsGeometry();
			// node.computeMass();

			locationBackup.add(new Vector3f(node.getWorldTranslation()));

			dynamicPins.add(node);
			i++;
		}
	}

	public void changeContactMaterial(Material contactedMaterial,
			float sliding, float bounciness) {
		Helpers.updateContactInfo(pinMaterial, contactedMaterial, sliding,
				bounciness);
		for (DynamicPhysicsNode dynaminPin : dynamicPins) {
			dynaminPin.setMaterial(pinMaterial);
		}

	}

	private void generateLocations(Vector3f center, int xSeparation,
			int ySeparation) {
		locations = new ArrayList<Vector3f>();
		locations.add(center);
		locations.add(center
				.subtract(new Vector3f(xSeparation, 0, ySeparation)));
		locations.add(center.subtract(new Vector3f(3 * xSeparation, 0,
				ySeparation)));
		locations.add(center
				.subtract(new Vector3f(-xSeparation, 0, ySeparation)));
		locations.add(center.subtract(new Vector3f(-3 * xSeparation, 0,
				ySeparation)));
		locations.add(center.subtract(new Vector3f(2 * xSeparation, 0, 0)));
		locations.add(center.subtract(new Vector3f(-2 * xSeparation, 0, 0)));
		locations.add(center
				.subtract(new Vector3f(xSeparation, 0, -ySeparation)));
		locations.add(center.subtract(new Vector3f(-xSeparation, 0,
				-ySeparation)));
		locations.add(center.subtract(new Vector3f(0, 0, -2 * ySeparation)));

	}

	public void reset(Node rootNode, boolean reattach) {

		int i = 0;

		for (DynamicPhysicsNode dynPin : dynamicPins) {
			if (reattach) {
				System.out.println("Debo reatachar");
				if (!rootNode.hasChild(dynPin)) {
					System.out.println("Reatacho");
					rootNode.attachChild(dynPin);
				}
			}
			dynPin.rest();
			dynPin.getLocalTranslation().set(locationBackup.get(i));
			dynPin.setActive(true);
			dynPin.setLocalRotation(new Quaternion(new float[] { 0, 0, 0 }));
			dynPin.setLinearVelocity(new Vector3f(0, 0, 0));
			dynPin.setAngularVelocity(new Vector3f(0, 0, 0));
			i++;
		}

		return;

	}

	public DynamicPhysicsNode getPinNode(int i) {
		return dynamicPins.get(i);
	}

	public ArrayList<Integer> getPinsDown(float courtToWall) {
		int i = 0;
		ArrayList<Integer> pinsDown = new ArrayList<Integer>();
		while (i < dynamicPins.size()) {
			if (isPinDown(dynamicPins.get(i), courtToWall)) {
				System.out.println("Pino: " + (i + 1) + " cayo");
				pinsDown.add(i);
			} else {
				System.out.println("Pino: " + (i + 1) + " NO cayo");
			}
			i++;
		}
		return pinsDown;

	}

	private boolean isPinDown(DynamicPhysicsNode pinNode, float courtToWall) {
		if (Math.abs(pinNode.getLocalRotation().x) > DELTAFALLEN
				|| Math.abs(pinNode.getLocalRotation().z) > DELTAFALLEN
				|| Math.abs(pinNode.getWorldTranslation().getZ()) < courtToWall - 1) {
			return true;

		}
		return false;

	}

	public void detachPin(int i) {
		dynamicPins.get(i).detachAllChildren();
	}

	public ArrayList<Pin> getPins() {
		return pins;
	}

	public void setPins(ArrayList<Pin> pins) {
		this.pins = pins;
	}

	public ArrayList<DynamicPhysicsNode> getDynamicPins() {
		return dynamicPins;
	}

	public void setDynamicPins(ArrayList<DynamicPhysicsNode> dynamicPins) {
		this.dynamicPins = dynamicPins;
	}

	public ArrayList<Vector3f> getLocations() {
		return locations;
	}

	public void setLocations(ArrayList<Vector3f> locations) {
		this.locations = locations;
	}

	public Material getPinMaterial() {
		return pinMaterial;
	}

	public void setPinMaterial(Material pinMaterial) {
		this.pinMaterial = pinMaterial;
	}

}
